/*
 Xern Entity Relocation Network
 Copyright (C) 2010-2011 Ronie Salgado <roniesalg@gmail.com>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
*/

#include "IOgreObject.hpp"
#include "SceneNode.hpp"

namespace XernOgre
{
	SceneNode::SceneNode(Ogre::SceneManager *scene, Ogre::SceneNode *node)
		: scene(scene), onode(node)
	{
	}

	SceneNode::~SceneNode()
	{
		if(onode != scene->getRootSceneNode())
			scene->destroySceneNode(onode);
	}

	IResource::ResourceFlags SceneNode::GetFlags() const
	{
		return RFL_NONE;
	}

	void SceneNode::UpdateState(boost::shared_ptr<IDataFilter> stateData)
	{
	}

	const uuid &SceneNode::GetId() const
	{
		return this->id;
	}

	void SceneNode::SetId(const uuid &id)
	{
		this->id = id;
	}

	void SceneNode::AddChild(boost::shared_ptr<ISceneNode> node)
	{
		boost::shared_ptr<SceneNode> snode =
				boost::dynamic_pointer_cast<SceneNode> (node);
		if(snode)
			onode->addChild(snode->onode);
	}

	void SceneNode::RemoveChild(boost::shared_ptr<ISceneNode> node)
	{
		boost::shared_ptr<SceneNode> snode =
				boost::dynamic_pointer_cast<SceneNode> (node);
		if(snode)
			onode->removeChild(snode->onode);
	}

	void SceneNode::AttachObject(boost::shared_ptr<IMovableObject> object)
	{
		boost::shared_ptr<IOgreObject> ogreObject =
			boost::dynamic_pointer_cast<IOgreObject> (object);
		if(ogreObject)
		{
			Ogre::MovableObject *movable = ogreObject->GetMovable();
			if(movable)
				onode->attachObject(movable);
			else
				ogreObject->DelayAttach(shared_from_this());
		}
	}

	void SceneNode::DetachObject(boost::shared_ptr<IMovableObject> object)
	{
		boost::shared_ptr<IOgreObject> ogreObject =
			boost::dynamic_pointer_cast<IOgreObject> (object);
		if(ogreObject)
		{
			Ogre::MovableObject *movable = ogreObject->GetMovable();
			if(movable)
				onode->detachObject(movable);
		}
	}

	void SceneNode::SetTransform(const ReversibleTransform &transform)
	{
		this->transform = transform;

		// Update the ogre scene node transform.
		Quaternion q = transform.GetRotation();
		Vector3 p = transform.GetVector();
		onode->setPosition(p.x, p.y, p.z);
		onode->setOrientation(Ogre::Quaternion(q.w, q.x, q.y, q.z));
	}

	const ReversibleTransform &SceneNode::GetTransform() const
	{
		return transform;
	}
}; // namespace XernOgre
